package com.gilight.base.admin.order;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gilight.base.admin.UtilServices;
import com.gilight.base.admin.brand.AdminBrandService;
import com.gilight.base.base.exception.AdminServiceException;
import com.gilight.base.base.exception.ExceptionDefinition;
import com.gilight.base.base.exception.ServiceException;
import com.gilight.base.component.LockComponent;
import com.gilight.base.component.LockConst;
import com.gilight.base.dao.SysZzjgMapper;
import com.gilight.base.dto.order.OrderDTO;
import com.gilight.base.dto.order.OrderStatisticsByDayDTO;
import com.gilight.base.dto.order.OrderStatisticsDTO;
import com.gilight.base.enums.DMQHandlerType;
import com.gilight.base.enums.OrderStatusType;
import com.gilight.base.enums.UserLoginType;
import com.gilight.base.mapper.OrderMapper;
import com.gilight.base.mapper.OrderSkuMapper;
import com.gilight.base.mapper.SkuMapper;
import com.gilight.base.model.BrandDo;
import com.gilight.base.model.Page;
import com.gilight.base.model.SysZzjg;
import com.gilight.base.model.order.OrderDO;
import com.gilight.base.model.order.OrderSkuDO;
import com.gilight.base.model.uni.UserDO;
import com.gilight.base.mq.DelayedMessageQueue;
import com.gilight.base.properties.UnimallOrderProperties;
import com.gilight.base.properties.UnimallWxAppProperties;
import com.gilight.base.properties.UnimallWxPayProperties;
import com.gilight.base.service.impl.UserBizService;
import com.gilight.base.service.order.OrderBizService;
import com.gilight.base.uiapp.order.OrderService;
import com.gilight.base.wx.WeChatCommonTemplateMessageModel;
import com.gilight.base.wx.WeChatTemplateValueModel;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.service.WxPayService;
import javafx.util.converter.LocalDateTimeStringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.File;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * Created by rize on 2019/7/10.
 */
@Service
public class AdminOrderServiceImpl implements AdminOrderService {

    private static final Logger logger = LoggerFactory.getLogger(AdminOrderServiceImpl.class);

    @Autowired
    private OrderBizService orderBizService;

    @Autowired
    private WxPayService wxPayService;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderSkuMapper orderSkuMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private LockComponent lockComponent;

    @Autowired
    private UserBizService userBizService;

    @Autowired
    private DelayedMessageQueue delayedMessageQueue;

    @Autowired
    private UnimallWxAppProperties unimallWxProperties;

    @Autowired
    private UnimallOrderProperties unimallOrderProperties;

    @Autowired
    private UnimallWxPayProperties unimallWxPayProperties;
    @Autowired
    private SysZzjgMapper zzjgMapper;
    @Autowired
    private UtilServices utilServices;

    @Autowired
    private OrderService orderService;

    @Autowired
    private AdminBrandService adminBrandService;


    @Override
    public Page<OrderDO> list(Integer page, Integer limit, Integer status, String orderNo, Long adminId, Long zzjgId,Long start,Long end) throws ServiceException {
        QueryWrapper<OrderDO> wrapper = new QueryWrapper<OrderDO>();
        if(zzjgId != 1L){
            //说明不是超级管理员
            wrapper.eq("zzjgid",zzjgId);
        }
        wrapper.orderByDesc("id");
        if (!StringUtils.isEmpty(orderNo)) {
            wrapper.eq("order_no", orderNo);
        }
        if (status != null) {
            wrapper.eq("status", status);
        }
        if(start !=null&&end!=null){
            wrapper.between("gmt_create", new Date(start), new Date(end));
        }
        return orderMapper.selectPage(Page.div(page, limit, OrderDO.class), wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String refund(String orderNo, Integer type, Integer sum, Long adminId, Long zzjgId) throws ServiceException {
        if (lockComponent.tryLock(LockConst.ORDER_REFUND_LOCK + orderNo, 30)) {
            try {
                //1.校验订单状态是否处于退款中
                OrderDO orderDO = orderBizService.checkOrderExistByNo(orderNo, null).get(0);
                if (orderDO.getStatus() != OrderStatusType.REFUNDING.getCode()) {
                    throw new AdminServiceException(ExceptionDefinition.ORDER_STATUS_NOT_SUPPORT_REFUND);
                }
                //2.退款处理
                if (type == 0) {
                    //2.1 店主拒绝退款
                    OrderDO updateOrderDO = new OrderDO();
                    // 判断之前是否已经发货，若没发货，则将状态流转到待发货
                    if (orderDO.getGmtShip() != null) {
                        updateOrderDO.setStatus(OrderStatusType.WAIT_CONFIRM.getCode());
                    } else {
                        updateOrderDO.setStatus(OrderStatusType.WAIT_STOCK.getCode());
                    }
                    updateOrderDO.setGmtUpdate(new Date());
                    orderBizService.changeOrderSubStatus(orderNo, OrderStatusType.REFUNDING.getCode(), updateOrderDO);
                    return "ok";
                } else if (type == 1) {
                    SysZzjg zzjg = zzjgMapper.selectByPrimaryKey(orderDO.getZzjgId());
                    WxPayService otherWxPayService = utilServices.getOtherISPService(zzjg);
                    String keyPath = unimallWxPayProperties.getKeyPath();
                    if(otherWxPayService!=null){
                        keyPath = otherWxPayService.getConfig().getKeyPath();
                    }
                    if (!new File(keyPath).exists()) {
                        throw new AdminServiceException(ExceptionDefinition.ORDER_REFUND_KEY_PATH_ERROR);
                    }
                    //2.2 店主同意退款
                    //2.2.1 先流转状态
                    OrderDO updateOrderDO = new OrderDO();
                    updateOrderDO.setStatus(OrderStatusType.REFUNDED.getCode());
                    updateOrderDO.setGmtUpdate(new Date());
                    //订单还库存
                    List<OrderSkuDO> orderSkuList = orderSkuMapper.selectList(new QueryWrapper<OrderSkuDO>().eq("order_id", orderDO.getId()));
                    orderSkuList.forEach(item -> {
                        skuMapper.returnSkuStock(item.getSkuId(), item.getNum());
                    });
                    orderBizService.changeOrderSubStatus(orderNo, OrderStatusType.REFUNDING.getCode(), updateOrderDO);
                    Long userId = orderDO.getUserId();
                    UserDO userDO = userBizService.getUserById(userId);
                    Integer loginType = userDO.getLoginType();
                    //2.2.2 向微信支付平台发送退款请求
                    Integer refundPrice = null;
                    if (sum != null) {
                        if (sum.intValue() > orderDO.getPayPrice()) {
                            throw new AdminServiceException(ExceptionDefinition.ORDER_REFUND_SUM_MOST_LOWER_THAN_PAY_PRICE);
                        }
                        refundPrice = sum;
                    } else {
                        refundPrice = orderDO.getPayPrice() - orderDO.getFreightPrice();
                    }
                    WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
                    wxPayRefundRequest.setAppid(loginType == UserLoginType.MP_WEIXIN.getCode() ? unimallWxProperties.getMiniAppId() : unimallWxProperties.getMiniAppSecret());
                    // 判断订单是子单支付还是父单支付
                    String abstractOrderNo;
                    if (orderDO.getSubPay().intValue() == 1) {
                        abstractOrderNo = orderDO.getOrderNo();
                    } else {
                        abstractOrderNo = orderDO.getParentOrderNo();
                    }
                    wxPayRefundRequest.setOutTradeNo(abstractOrderNo);
                    wxPayRefundRequest.setOutRefundNo("refund_" + abstractOrderNo);
                    wxPayRefundRequest.setTotalFee(orderDO.getPayPrice());
                    wxPayRefundRequest.setRefundFee(refundPrice);
                    wxPayRefundRequest.setSubMchId(zzjg.getMchId());
                    /**
                     * 当有其它服务商时要用其它服务商
                     */
                    WxPayRefundResult wxPayRefundResult = null;
                    if(otherWxPayService!=null){
                        wxPayRefundResult = otherWxPayService.refund(wxPayRefundRequest);
                    }else {
                        /* 其它服务商加载完毕 */
                        //todo需要传入子商户号
                        wxPayRefundResult = wxPayService.refund(wxPayRefundRequest);
                    }
                    if (!wxPayRefundResult.getReturnCode().equals("SUCCESS")) {
                        logger.warn("[微信退款] 失败 : " + wxPayRefundResult.getReturnMsg());
                        throw new AdminServiceException(wxPayRefundResult.getReturnMsg(),
                                ExceptionDefinition.THIRD_PART_SERVICE_EXCEPTION.getCode());
                    }
                    if (!wxPayRefundResult.getResultCode().equals("SUCCESS")) {
                        logger.warn("[微信退款] 失败 : " + wxPayRefundResult.getReturnMsg());
                        throw new AdminServiceException(wxPayRefundResult.getReturnMsg(),
                                ExceptionDefinition.THIRD_PART_SERVICE_EXCEPTION.getCode());
                    }
                    return "ok";
                } else {
                    throw new AdminServiceException(ExceptionDefinition.PARAM_CHECK_FAILED);
                }
            } catch (ServiceException e) {
                throw e;
            } catch (Exception e) {
                logger.error("[微信退款] 异常", e);
                throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);
            } finally {
                lockComponent.release(LockConst.ORDER_REFUND_LOCK + orderNo);
            }
        } else {
            throw new AdminServiceException(ExceptionDefinition.SYSTEM_BUSY);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String ship(String orderNo, String shipCode, String shipNo, Long adminId, Long zzjgId) throws ServiceException {
        orderBizService.checkOrderExistByNo(orderNo, null).get(0);
        OrderDO updateOrderDO = new OrderDO();
        Date now = new Date();
        updateOrderDO.setGmtUpdate(now);
        updateOrderDO.setGmtShip(now);
        updateOrderDO.setStatus(OrderStatusType.WAIT_CONFIRM.getCode());
        if (!"NONE".equals(shipCode)) {
            updateOrderDO.setShipCode(shipCode);
            updateOrderDO.setShipNo(shipNo);
        }
        //流转订单状态
        orderBizService.changeOrderSubStatus(orderNo, OrderStatusType.WAIT_STOCK.getCode(), updateOrderDO);
        // 发送自动确认收货延时消息
        delayedMessageQueue.publishTask(DMQHandlerType.ORDER_AUTO_CONFIRM.getCode(), orderNo, unimallOrderProperties.getAutoConfirmTime());
        this.notyUserGetSku(orderNo);
        return "ok";
    }

    private void notyUserGetSku(String orderNo) throws ServiceException {
        try {
                String parentOrderNo = orderNo.substring(0, orderNo.indexOf('S'));
                OrderDTO orderDTO = orderService.getOrderDetail(null,null,parentOrderNo);
                String quCanMa = orderDTO.getSpecOrder();
                if(org.apache.commons.lang3.StringUtils.isEmpty(quCanMa)){
                    quCanMa = "1";
                }
                quCanMa = quCanMa.replace("M","");
                Date date = orderDTO.getGmtCreate(); //聚餐时间
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String stringDate = simpleDateFormat.format(date); //下单时间
                Long userId = orderDTO.getUserId();
                UserDO userDo = userBizService.getUserById(userId);
                String openId = userDo.getOpenId();
                List<Map<String, Object>> orderSkuDOMaps = orderService.getOrderSku(orderNo);
                String skuTiles="饮品";
                String specTitles = "";
                for(Map<String,Object> item : orderSkuDOMaps){
                    skuTiles+=item.get("title")+"等"+orderSkuDOMaps.size()+"个饮品";
                    specTitles = item.get("specification")+"";
                    break;
                }
                if(org.apache.commons.lang3.StringUtils.isEmpty(specTitles)){
                    specTitles="规格：无";
                }
                SysZzjg zzjg = orderDTO.getZzjg();
                Long brandId = zzjg.getBrandId();
                BrandDo brand = adminBrandService.getById(brandId);
                String appId = brand.getMiniAppId();
                String appSec = brand.getMiniAppSec();
                String accessToken = userBizService.getWxMiniAccessToken(appId,appSec);
                String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token="+accessToken;
                WeChatCommonTemplateMessageModel model = new WeChatCommonTemplateMessageModel();
                model.setTouser(openId);
                model.setTemplate_id("4rmQ2k5SfYncpijWA04m2bmhav4xahmD449u_c6XH20");
                model.setPage("pages/order/detail?id=" + orderDTO.getId());
                Map<String, WeChatTemplateValueModel> datas = new HashMap<>();
                WeChatTemplateValueModel vModel = new WeChatTemplateValueModel();
                vModel.setValue(quCanMa);
                datas.put("character_string12",vModel);

                WeChatTemplateValueModel vModelDate = new WeChatTemplateValueModel();
                vModelDate.setValue(stringDate);
                datas.put("date3",vModelDate);


                WeChatTemplateValueModel vModelSkuTitle= new WeChatTemplateValueModel();
                vModelSkuTitle.setValue(skuTiles);
                datas.put("thing6",vModelSkuTitle);
                WeChatTemplateValueModel vModelSkuTitleGg= new WeChatTemplateValueModel();
                vModelSkuTitleGg.setValue(specTitles);
                datas.put("thing11",vModelSkuTitleGg);

                WeChatTemplateValueModel vModelSkuTitleTX= new WeChatTemplateValueModel();
                vModelSkuTitleTX.setValue("您的餐品已制作完成，请到前台领取");
                datas.put("thing7",vModelSkuTitleTX);
                model.setData(datas);

                userBizService.wechatCommonTemplateMessage(model,url);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public OrderDTO detail(Long orderId, Long adminId) throws ServiceException {
        return orderBizService.getOrderDetail(orderId, null, null);
    }

    @Override
    public List<OrderDTO> queryToExcel(Long gmtStart, Long gmtEnd, Integer status, Long adminId, Long zzjgId) throws ServiceException {
        QueryWrapper wrapper = new QueryWrapper<OrderDTO>();
        if (gmtStart != null && gmtEnd != null) {
            if (gmtStart > gmtStart) {
                throw new AdminServiceException(ExceptionDefinition.ORDER_EXCEL_PARAM_ERROR);
            }
            wrapper.between("gmt_create", new Date(gmtStart), new Date(gmtEnd));
        }
        if (status != null) {
            wrapper.eq("status", status);
        }
        if(zzjgId!=null){
            wrapper.eq("zzjgid", zzjgId);
        }
        wrapper.orderByDesc("gmt_create");
        List<OrderDO> orderDOS = orderMapper.selectList(wrapper);
        if (orderDOS == null || orderDOS.size() == 0) {
            return null;
        }
        List<OrderDTO> orderDTOList = new ArrayList<>();
        for (OrderDO temp : orderDOS) {
            OrderDTO orderDTO = new OrderDTO();
            BeanUtils.copyProperties(temp, orderDTO);
            orderDTOList.add(orderDTO);
        }
        for (OrderDTO orderDTO : orderDTOList) {
            List<OrderSkuDO> orderSkuDOList = orderSkuMapper.selectList(new QueryWrapper<OrderSkuDO>().eq("order_no", orderDTO.getOrderNo()));
            orderDTO.setSkuList(orderSkuDOList);
        }
        return orderDTOList;
    }

    @Override
    public String editAdminMono(Long orderId, Integer level, String mono, Long adminId) throws ServiceException {
        OrderDO orderDO = new OrderDO();
        orderDO.setId(orderId);
        orderDO.setAdminMonoLevel(level);
        orderDO.setAdminMono(mono);
        orderDO.setGmtUpdate(new Date());
        if (orderMapper.updateById(orderDO) > 0) {
            return "ok";
        }
        throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);
    }

    @Override
    public List<OrderStatisticsDTO> statistics(Long gmtStart, Long gmtEnd, Long adminId, Long zzjgId) throws ServiceException {
        if (gmtStart == null) {
            gmtStart = System.currentTimeMillis() - 1000l * 60 * 60 * 24;
        }
        if (gmtEnd == null) {
            gmtEnd = System.currentTimeMillis();
        }
        if (gmtStart > gmtStart) {
            throw new AdminServiceException(ExceptionDefinition.ORDER_EXCEL_PARAM_ERROR);
        }
        if(zzjgId ==null){
            zzjgId = 1L;
        }
//        List<OrderDO> orderDOS = orderMapper.selectList(
//                new QueryWrapper<OrderDO>()
//                        .between("gmt_create", new Date(gmtStart), new Date(gmtEnd)).eq("zzjgid",zzjgId)
//                        .select("id"));
//        List<Long> ids = orderDOS.stream().map(item -> item.getId()).collect(Collectors.toList());
//        if (CollectionUtils.isEmpty(ids)) {
//            return null;
//        }
        List<OrderStatisticsDTO> statistics = orderSkuMapper.statisticsNew(zzjgId,new Date(gmtStart),new Date(gmtEnd));
       // List<OrderStatisticsDTO> statistics = orderSkuMapper.statistics(ids);
        return statistics;
    }

    @Override
    public List<OrderStatisticsByDayDTO>  statisticsByDay(Long gmtStart, Long gmtEnd, Long adminId, Long zzjgId) throws AdminServiceException {
        if (gmtStart == null) {
            gmtStart = System.currentTimeMillis() - 1000l * 60 * 60 * 24;
        }
        if (gmtEnd == null) {
            gmtEnd = System.currentTimeMillis();
        }
        if (gmtStart > gmtStart) {
            throw new AdminServiceException(ExceptionDefinition.ORDER_EXCEL_PARAM_ERROR);
        }
        if(zzjgId ==null){
            zzjgId = 1L;
        }
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //制定输出格式
//        String s = sdf.format(new Date(gmtStart));
//        String e = sdf.format(new Date(gmtEnd));
        List<OrderStatisticsByDayDTO> orderStatisticsByDayDTOS = orderSkuMapper.statisticsByDay(zzjgId, new Date(gmtStart), new Date(gmtEnd));
        return orderStatisticsByDayDTOS;
    }
    @Override
    public Object statisticsByDayWx(Long gmtStart, Long gmtEnd, Long adminId, Long zzjgId) throws ServiceException {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
        Date date = new Date(gmtStart);
        String dateStr = sdf.format(date);
        return  orderService.downWxBill(zzjgId,dateStr);
    }

}
